package com.open.capacity.user.service.impl;

import com.open.capacity.commons.Result;
import com.open.capacity.finance.util.uuid.UUIDUtils;
import com.open.capacity.model.system.*;
import com.open.capacity.user.dao.*;
import com.open.capacity.user.enums.AuthorizeItemTypes;
import com.open.capacity.user.model.SysAuthorize;
import com.open.capacity.user.service.SysAuthorizeService;
import com.open.capacity.user.service.SysMenuService;
import com.open.capacity.utils.SysUserUtil;
import com.open.capacity.vo.SysMenuVo;
import com.open.capacity.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Autowired
    private SysMenuDao menuDao;

    @Autowired
    private SysMenuButtonDao menuButtonDao;

    @Autowired
    private SysMenuColumnDao menuColumnDao;

    @Autowired
    private SysAuthorizeService authorizeService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> saveOrUpdate(SysMenu menu, Set<SysMenuButton> btns, Set<SysMenuColumn> cols) {
        int i = 0;
        if (StringUtils.isNotEmpty(menu.getId())) {
            SysMenu model = menuDao.findById(menu.getId());
            if (model != null) {
                menu.setUpdateTime(new Date());
                i = menuDao.updateByOps(menu);
            }
        } else {
            if (menu.getParentId() == null) {
                menu.setParentId("0");
            }
            menu.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            menu.setHidden(0);
            menu.setCategory("0");
            menu.setCreateTime(new Date());
            menu.setUpdateTime(menu.getCreateTime());
            i = menuDao.save(menu);
        }
        if (CollectionUtils.isNotEmpty(btns)) {
            saveMenuButtons(menu.getId(), btns);
        }
        if (!CollectionUtils.isEmpty(cols)) {
            saveMenuColumns(menu.getId(), cols);
        }

        return i > 0 ? Result.succeed(menu.getId(), "操作成功") : Result.failed("操作失败");
    }

    /**
     * 保存菜单按钮
     */
    private void saveMenuButtons(String menuId, Set<SysMenuButton> btns) {
        //删除原有数据
        menuButtonDao.deleteByMenuId(menuId);
        //新增新数据
        btns.forEach(r -> {
            r.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            r.setMenuId(menuId);
            menuButtonDao.save(r);
        });
    }

    /**
     * 保存菜单列
     */
    private void saveMenuColumns(String menuId, Set<SysMenuColumn> cols) {
        //删除原有数据
        menuColumnDao.deleteByMenuId(menuId);
        //新增新数据
        cols.forEach(r -> {
            r.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            r.setMenuId(menuId);
            menuColumnDao.save(r);
        });
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id) {
        SysMenu menu = menuDao.findById(id);

        //menuDao.deleteByParentId(menu.getId());
        menuButtonDao.deleteByMenuId(id);
        menuColumnDao.deleteByMenuId(id);

        menuDao.delete(id);

        log.info("删除菜单：{}", menu);
    }


    @Override
    public List<SysMenuVo> findAll(Map<String, Object> params) {
        List<SysMenu> list = menuDao.findList(params);
        List<SysMenuVo> extList = new ArrayList<>();
        for (SysMenu menu : list) {
            SysMenuVo ext = new SysMenuVo();
            ext.setMenu(menu);
            if (!menu.getTarget().equals("expand")) {
                Set<SysMenuButton> buttons = menuButtonDao.findByMenuId(menu.getId());
                Set<SysMenuColumn> columns = menuColumnDao.findByMenuId(menu.getId());
                ext.setMenuColumns(columns);
                ext.setMenuBtns(buttons);
            }
            extList.add(ext);
        }
        return extList;
    }

    @Override
    public List<SysMenu> findByRoles(Set<Long> roles) {
        return menuDao.findByRoles(roles);
    }

    @Override
    public List<SysMenu> findMenus(Map<String, Object> params) {
        List<SysMenu> list = menuDao.findList(params);
        return list;
    }

    @Override
    public List<SysMenu> findByParentId(String parentId) {
        return menuDao.findByParentId(parentId);
    }

    @Override
    public SysMenu findByPath(String path) {
        SysMenu menu = menuDao.findByPath(path);
        if (menu != null) {
            List<SysMenuButton> buttons = new ArrayList<>();
            List<SysMenuColumn> columns = new ArrayList<>();
            LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
            if (loginAppUser.getId().equals("1")) {
                buttons = new ArrayList<>(menuButtonDao.findByMenuId(menu.getId()));
                columns = new ArrayList<>(menuColumnDao.findByMenuId(menu.getId()));
            } else {
                Set<SysRole> roles = loginAppUser.getSysRoles();
                if (CollectionUtils.isNotEmpty(roles)) {
                    buttons = menuButtonDao.findByRoles(menu.getId(), roles.parallelStream().map(SysRole::getId).collect(Collectors.toSet()));
                    columns = menuColumnDao.findByRoles(menu.getId(), roles.parallelStream().map(SysRole::getId).collect(Collectors.toSet()));
                }
            }

            Map<String, String> mCols = columns.stream().collect(Collectors.toMap(SysMenuColumn::getCode, SysMenuColumn::getName, (key1, key2) -> key2));
            Map<String, String> mBtns = buttons.stream().collect(Collectors.toMap(SysMenuButton::getCode, SysMenuButton::getName, (key1, key2) -> key2));

            menu.setCols(mCols);
            menu.setBtns(mBtns);
        }
        return menu;
    }

    @Override
    public SysMenuVo findById(String id) {
        SysMenu menu = menuDao.findById(id);
        SysMenuVo ext = new SysMenuVo();
        ext.setMenu(menu);
        if (!menu.getTarget().equals("expand")) {
            Set<SysMenuButton> buttons = menuButtonDao.findByMenuId(id);
            Set<SysMenuColumn> columns = menuColumnDao.findByMenuId(id);
            ext.setMenuColumns(columns);
            ext.setMenuBtns(buttons);
        }
        return ext;
    }

}
